package org.spring.aicloud.controller.model;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.spring.aicloud.entity.Answer;
import org.spring.aicloud.entity.myenum.AiModelEnum;
import org.spring.aicloud.entity.myenum.AiTypeEnum;
import org.spring.aicloud.service.IAnswerService;
import org.spring.aicloud.util.AppVariable;
import org.spring.aicloud.util.ResponseEntity;
import org.spring.aicloud.util.SecurityUtil;
import org.springframework.ai.image.ImagePrompt;
import org.springframework.ai.image.ImageResponse;
import org.springframework.ai.openai.OpenAiChatClient;
import org.springframework.ai.openai.OpenAiImageClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 调用云端OpenAI大模型
 */
@RestController
@RequestMapping("/openai")
@Tag(name = "ChatGPT大模型")
public class OpenAIController {
   @Resource   //OpenAiChatClient1.0版本之后的名字
    private OpenAiChatClient chatModel;
   @Resource
   private OpenAiImageClient imageModel;
   @Resource
   private IAnswerService answerService;
   @Resource
   private RedissonClient redissonClient;
   @Resource
   private RedisTemplate<String,Object> redisTemplate;
    /**
     * 调用OpenAi的聊天接口
     * @param question
     * @return
     */
   @RequestMapping("/chat")
   public ResponseEntity chat(String question){
       if (!StringUtils.hasLength(question)){
           return ResponseEntity.fail("问题不能为空");
       }
       //在调用接口之前，先针对用户加锁
       //创建key
       String lockKey = AppVariable.getModelLockKey
               (SecurityUtil.getCurrentUser().getUid(),
                       AiModelEnum.OPENAI.getValue(), AiTypeEnum.CHAT.getValue());
       String result = ""; //大模型返回的结果
       boolean save = false;//数据是否保存成功
       //创建分布式锁实例
       RLock lock = redissonClient.getLock(lockKey);
       //尝试获取分布式锁
       boolean isLock = false;
       try {
           isLock = lock.tryLock(10, TimeUnit.SECONDS);
       } catch (InterruptedException e) {
           throw new RuntimeException(e);
       }
       if (!isLock) {
           //获取分布式锁失败
           return ResponseEntity.fail("请勿频繁调用接口");
       }
       try {
           //获取锁成功，开始执行业务逻辑
           //调用openAI接口
           result = chatModel.call(question);
           //将结果保存到数据库中
           Answer answer = new Answer();
           answer.setTitle(question);
           answer.setContent(result);
           answer.setType(AiTypeEnum.CHAT.getValue());
           answer.setModel(AiModelEnum.OPENAI.getValue());
           //根据SpringSecurity获取当前登录的用户id
           answer.setUid(SecurityUtil.getCurrentUser().getUid());
           save = answerService.save(answer);
       }catch (Exception ignored){}
       finally {
           //释放锁
           lock.unlock();
       }
       if (!save){
           return ResponseEntity.fail("数据保存失败!");
       }
       return ResponseEntity.success(result);
   }

   @RequestMapping("/draw")
    public ResponseEntity draw(String question){
        if (!StringUtils.hasLength(question)){
            return ResponseEntity.fail("问题不能为空");
        }
       //在调用接口之前，先针对用户加锁
       //创建key
       String lockKey = AppVariable.getModelLockKey
               (SecurityUtil.getCurrentUser().getUid(),
                       AiModelEnum.OPENAI.getValue(), AiTypeEnum.DRAW.getValue());
       String imageUrl = ""; //大模型返回的结果
       boolean save = false;//数据是否保存成功
       //创建分布式锁实例
       RLock lock = redissonClient.getLock(lockKey);
       //尝试获取分布式锁
       boolean isLock = false;
       try {
           isLock = lock.tryLock(10, TimeUnit.SECONDS);
       } catch (InterruptedException e) {
           throw new RuntimeException(e);
       }
       if (!isLock) {
           //获取分布式锁失败
           return ResponseEntity.fail("请勿频繁调用接口");
       }
       try {
           //调用openAI接口
           ImageResponse result = imageModel.call(new ImagePrompt(question));
           //拿到图片的url地址
           imageUrl = result.getResult().getOutput().getUrl();
           //将结果保存到数据库中
           Answer answer = new Answer();
           answer.setTitle(question);
           answer.setContent(imageUrl);
           //2=绘画
           answer.setType(AiTypeEnum.DRAW.getValue());
           answer.setModel(AiModelEnum.OPENAI.getValue());
           answer.setUid(SecurityUtil.getCurrentUser().getUid());
           save = answerService.save(answer);
       }catch (Exception ignored){}
       finally {
           //释放锁
           lock.unlock();
       }
      if (save){
          //将结果返回给前端，前端就可以结果中取到图片的url地址，然后进行展示。
          return ResponseEntity.success(imageUrl);
      }
      return ResponseEntity.fail("数据保存失败,请重试!");
    }

    /**
     * 获取openAI的历史聊天信息
     * @return
     */
    @RequestMapping("/getchatlist")
    public ResponseEntity getChatList() {
        //首先获取到当前的登录用户和调用的大模型
        long uid = SecurityUtil.getCurrentUser().getUid();
        int type = AiTypeEnum.CHAT.getValue();
        int model = AiModelEnum.OPENAI.getValue();
        //将当前的uid和type和model封装成一个key
        String cacheKey = AppVariable.getListCacheKey(uid,model,type);
        Object value = redisTemplate.opsForValue().get(cacheKey);
        if (value == null){
            //缓存不存在,就去查询数据库
            //根据uid查询出所有的聊天记录
            QueryWrapper<Answer> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("uid",uid);
            queryWrapper.eq("type",type);
            queryWrapper.eq("model",model);
            //使用主键进行排序，直接使用聚簇索引，不适用createtime
            queryWrapper.orderByDesc("aid");
            List<Answer> list = answerService.list(queryWrapper);
            //查询到结果之后存储到缓存当中
            redisTemplate.opsForValue().set(cacheKey,list,1,TimeUnit.DAYS );
            //存储完成之后，将查询结果返回
            return ResponseEntity.success(list);
        }else {
            return ResponseEntity.success(value);
        }
    }

    /**
     * 获取openAI下的历史绘画列表
     */
    @RequestMapping("/getdrawlist")
    public ResponseEntity getDrawList(){
        QueryWrapper<Answer> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("uid",SecurityUtil.getCurrentUser().getUid());
        queryWrapper.eq("type",AiTypeEnum.DRAW.getValue());
        queryWrapper.eq("model",AiModelEnum.OPENAI.getValue());
        queryWrapper.orderByDesc("aid");
        List<Answer> list = answerService.list(queryWrapper);
        return ResponseEntity.success(list);
    }
}
